import io
from datetime import date, datetime
from typing import List, Union, Optional, Dict
import struct
import peewee
from emi.bar.data import Interval
from emi.bar.storage.model import BaseDBModel
from emi.core.DBSource import DBSource
from emi.trade.data import OrderData, Direction, Offset,OpType,OrderType,Status
from emi.util import NumUtils
from emi.io import write_float_compress, read_float_compress, write_int_compress, read_int_compress, write_str_list, \
    read_str_list


# id: str = None
# symbol: str
# direction: Direction

# offset: Offset
# type: OrderType
# status: Status = None
# op_type: OpType = OpType.UNKONW

# price: float
# volume: int  # 请求仓位
# volume_traded: float = 0  # 成交仓位
# frozen_money: float = 0  # 属于冻结资金,用来开仓的资金,得考虑佣金情况。
# need_open_money: float = 0  # 需要的开仓资金（成交所需要的资金）

# create_time: datetime = None
# update_time: datetime = None

# description: str = ""  # 描述
# msg: str = None  # 备注信息

class OrderDataModel(BaseDBModel):

    id: str = peewee.CharField(primary_key=True, max_length=128)
    symbol: str = peewee.CharField(index=True, max_length=64)
    direction: str = peewee.CharField(max_length=16)
    offset: str = peewee.CharField(max_length=16)
    type: str = peewee.CharField(max_length=16)
    status: str = peewee.CharField(max_length=16)
    op_type: str = peewee.CharField(max_length=16)

    price: float = peewee.DoubleField(null=False)
    volume: int = peewee.IntegerField(null=False)
    volume_traded: int = peewee.IntegerField(null=False)
    frozen_money: float = peewee.DoubleField(null=False)
    need_open_money: float = peewee.DoubleField(null=False)
    create_time: datetime = peewee.TimestampField(index=True)
    update_time: datetime = peewee.TimestampField(index=True)
    description: str = peewee.CharField(max_length=1024)
    msg: str = peewee.CharField(max_length=1024)


    def to_dict(self):
        return self.__data__

    @staticmethod
    def from_data(bar: OrderData):
        model = OrderDataModel()
        model.id = bar.id
        model.symbol = bar.symbol
        model.direction = bar.direction.value
        model.offset = bar.offset.value
        model.type = bar.type.value
        model.status = bar.status.value
        model.op_type = bar.op_type.value
        model.price = bar.price
        model.volume = bar.volume
        model.volume_traded = bar.volume_traded
        model.frozen_money = bar.frozen_money
        model.need_open_money = bar.need_open_money
        model.create_time = bar.create_time
        model.update_time = bar.update_time
        model.description = bar.description
        model.msg = bar.msg

        return model

    def to_bar(self) -> OrderData:
        bar = OrderData(
            id=self.id,
            symbol=self.symbol,
            direction=Direction(self.direction),
            offset=Offset(self.offset),
            type=OrderType(self.type),
            status=Status(self.status),
            op_type=OpType(self.op_type),
            price=self.price,
            volume=self.volume,
            volume_traded=self.volume_traded,
            frozen_money=self.frozen_money,
            need_open_money=self.need_open_money,
            create_time=self.create_time,
            update_time=self.update_time,
            description=self.description,
            msg=self.msg,
        )
        return bar


class OrderDataStorage:

    def __init__(self, source: DBSource, table_name=None):
        # indexes_desc = (
        #     (("dimen_value", "interval", "datetime"), True),
        # )
        if table_name is None:
            table_name = 't_order'
        self.source = source.init_peewee(table_name, OrderDataModel, indexes=None, ignore_inited=True)

    def save_bars(self, bars: List[OrderData]):
        """
        保存Bar数据。
        """
        ds = [OrderDataModel.from_data(i) for i in bars]
        with self.source.use_peewee() as db_model:
            db_model.save_all(ds)


    def size(self) -> int:
        with self.source.use_peewee() as db_model:
            return db_model.select().count()

    def clear(self):
        with self.source.use_peewee() as db_model:
            db_model.drop_table()
            db_model.create_table()

    def get_all(self) -> List[OrderData]:
        """
        返回指定日期的量化数据。
        :param dimen:
        :param interval:
        :param tag:
        :return:
        """
        with self.source.use_peewee() as db_model:

            s = db_model.select()
            if s:
                return [db_bar.to_bar() for db_bar in s]
        return []
